﻿#pragma once
#include "yzrutil.h"
#include "DSP.h"
#include "IIR.h"
#include "IIRUtil.h"
#include "RingBuffer.h"
#include "array/Arrays.h"
#include "collection/ArrayList.hpp"
#include "array/Array.hpp"
#include <vector>

namespace yzrilyzr_dsp{
	ECLASS(FDNReverb, public DSP){
	private:
	struct DelayLine{
		RingBufferSample * buffer;
		std::shared_ptr<IIR> decayFilter;
		u_sample outputHistory;
	};

	std::vector<DelayLine> mDelayLines;
	std::vector<std::vector<u_sample>> mFeedbackMatrix;
	std::vector<u_sample> mInputWeights;
	std::vector<u_sample> mOutputWeights;

	u_sample mFeedbackGain=0;
	u_sample wetRatio=0;
	u_sample mLowpassCoeff=0;
	u_sample mHighpassCoeff=0;
	bool mUseDecayFilters=false;

	public:
	FDNReverb()=default;

	// 灵活构造函数，可以自定义所有参数
	FDNReverb(const std::vector<u_index> &delayLengths,
			  const std::vector<std::vector<u_sample>> &feedbackMatrix,
			  u_sample feedbackGain,
			  u_sample mixAmount,
			  u_sample lowpassCoeff=0.0,
			  u_sample highpassCoeff=0.0,
			  bool useDecayFilters=false)
		: mFeedbackGain(feedbackGain),
		wetRatio(mixAmount),
		mLowpassCoeff(lowpassCoeff),
		mHighpassCoeff(highpassCoeff),
		mUseDecayFilters(useDecayFilters){
		initialize(delayLengths, feedbackMatrix);
	}

	// 简化构造函数，使用默认Hadamard矩阵
	FDNReverb(const std::vector<u_index> &delayLengths,
			  u_sample feedbackGain,
			  u_sample mixAmount,
			  u_sample lowpassCoeff=0.0,
			  u_sample highpassCoeff=0.0)
		: mFeedbackGain(feedbackGain),
		wetRatio(mixAmount),
		mLowpassCoeff(lowpassCoeff),
		mHighpassCoeff(highpassCoeff),
		mUseDecayFilters(true){
		auto matrix=createDefaultFeedbackMatrix(delayLengths.size());
		initialize(delayLengths, matrix);
	}

	~FDNReverb() override{}

	std::shared_ptr<DSP> cloneDSP() override{
		return std::make_shared<FDNReverb>();
	}

	void init(u_sample_rate sampleRate) override{
		for(u_index i=0; i < mDelayLines.size(); ++i){
			if(mUseDecayFilters){
				u_sample delayTimeSamples=static_cast<u_sample>(mDelayLines[i].buffer->capacity());
				mDelayLines[i].decayFilter=IIRUtil::newC1C3IIRFilter(sampleRate / delayTimeSamples,
																	 mLowpassCoeff, mHighpassCoeff);
			}
		}
	}

	void resetMemory() override{
		for(auto & line : mDelayLines){
			line.buffer->reset();
			line.outputHistory=0.0;
			if(line.decayFilter){
				line.decayFilter->resetMemory();
			}
		}
	}

	u_sample procDsp(u_sample input) override{
		std::vector<u_sample> tempInputs(mDelayLines.size(), 0.0);
		u_sample output=0.0;

		// 计算每个延迟线的输入
		for(u_index i=0; i < mDelayLines.size(); ++i){
			tempInputs[i]=mInputWeights[i] * input;

			for(u_index j=0; j < mDelayLines.size(); ++j){
				tempInputs[i]+=mFeedbackMatrix[i][j] * mDelayLines[j].outputHistory;
			}
		}

		// 处理每个延迟线
		for(u_index i=0; i < mDelayLines.size(); ++i){
			auto & line=mDelayLines[i];

			// 写入新样本
			line.buffer->write(tempInputs[i]);

			// 读取延迟样本并应用衰减滤波
			u_sample delayed=line.buffer->oldest();
			if(line.decayFilter){
				delayed=line.decayFilter->procDsp(delayed);
			}

			line.outputHistory=delayed;
			output+=mOutputWeights[i] * delayed;
		}

		return static_cast<u_sample>(wetRatio * output + (1.0 - wetRatio) * input);
	}

	void cloneParam(DSP * obj1) override{
		if(auto other=dynamic_cast<FDNReverb *>(obj1)){
			mFeedbackGain=other->mFeedbackGain;
			wetRatio=other->wetRatio;
			mLowpassCoeff=other->mLowpassCoeff;
			mHighpassCoeff=other->mHighpassCoeff;
			mUseDecayFilters=other->mUseDecayFilters;

			// 深度拷贝延迟线配置
			mDelayLines=other->mDelayLines;
			mFeedbackMatrix=other->mFeedbackMatrix;
			mInputWeights=other->mInputWeights;
			mOutputWeights=other->mOutputWeights;
		}
	}

	private:
	void initialize(const std::vector<u_index> &delayLengths,
					const std::vector<std::vector<u_sample>> &feedbackMatrix){
		u_index numDelays=delayLengths.size();

		// 初始化延迟线
		mDelayLines.resize(numDelays);
		for(u_index i=0; i < numDelays; ++i){
			mDelayLines[i].buffer=new RingBufferSample(delayLengths[i]);
			mDelayLines[i].decayFilter=nullptr;
			mDelayLines[i].outputHistory=0.0;
		}

		// 设置反馈矩阵
		mFeedbackMatrix=feedbackMatrix;

		// 设置默认输入/输出权重
		mInputWeights.assign(numDelays, 1.0 / numDelays);
		mOutputWeights.assign(numDelays, 1.0 / numDelays);

		// 调整输出权重符号以增加扩散
		for(u_index i=1; i < numDelays; i+=2){
			mOutputWeights[i]=-mOutputWeights[i];
		}
	}

	static std::vector<std::vector<u_sample>> createDefaultFeedbackMatrix(u_index size){
		std::vector<std::vector<u_sample>> matrix(size, std::vector<u_sample>(size));

		// 创建简单的Hadamard风格矩阵
		for(u_index i=0; i < size; ++i){
			for(u_index j=0; j < size; ++j){
				matrix[i][j]=(i == j)?1.0:-1.0 / (size - 1);
			}
		}

		return matrix;
	}
	yzrilyzr_lang::String toString()const override;
	};
}